#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
Simplified BSD License (BSD)
Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this 
      list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice, 
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF SUCH DAMAGE.
*/
#endregion

#region Record of Change
//             							CHANGE HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | DEVELOPER  | DESCRIPTION                                              |
// -------------------------------------------------------------------------------------
// | 08-Nov-09 | HaiNM      | First creation.                                          |
// -------------------------------------------------------------------------------------
//
#endregion

#region Record of Audit
//             							REVIEW HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | REVIEWER   | NOTES                                                    |
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
//
#endregion

#region Using directives
using System;
using System.Globalization;

using Thn;
using Thn.Interface.Vcl;
#endregion

namespace Thn.Interface.Utils
{
    /// <summary>
    /// A helper class for various datetime related routines.
    /// </summary>
#if DEBUG
    public
#else
    public
#endif
 class DateTimeHelper
    {
        #region First / Last date

        #region Week
        /// <summary>
        /// return the first date in a given week (assuming the first day is Monday)
        /// </summary>
        public static DateTime FirstDateOfWeek(DateTime t)
        {
            DateTime result = DateTime.Now;

            switch (t.DayOfWeek)
            {
                case DayOfWeek.Monday:
                    result = t;
                    break;

                case DayOfWeek.Tuesday:
                    result = t.AddDays(-1);
                    break;

                case DayOfWeek.Wednesday:
                    result = t.AddDays(-2);
                    break;

                case DayOfWeek.Thursday:
                    result = t.AddDays(-3);
                    break;

                case DayOfWeek.Friday:
                    result = t.AddDays(-4);
                    break;

                case DayOfWeek.Saturday:
                    result = t.AddDays(-5);
                    break;

                case DayOfWeek.Sunday:
                    result = t.AddDays(-6);
                    break;
            }

            return result;
        }

        /// <summary>
        /// return the last date in a given week (assuming the last day is Sunday)
        /// </summary>
        public static DateTime LastDateOfWeek(DateTime t)
        {
            DateTime result = DateTime.Now;

            switch (t.DayOfWeek)
            {
                case DayOfWeek.Monday:
                    result = t.AddDays(6);
                    break;

                case DayOfWeek.Tuesday:
                    result = t.AddDays(5);
                    break;

                case DayOfWeek.Wednesday:
                    result = t.AddDays(4);
                    break;

                case DayOfWeek.Thursday:
                    result = t.AddDays(3);
                    break;

                case DayOfWeek.Friday:
                    result = t.AddDays(2);
                    break;

                case DayOfWeek.Saturday:
                    result = t.AddDays(1);
                    break;

                case DayOfWeek.Sunday:
                    result = t;
                    break;
            }

            return result;
        }
        #endregion

        #region Month
        /// <summary>
        /// return the first date in a given month
        /// </summary>
        public static DateTime FirstDateOfMonth(DateTime t)
        {
            return new DateTime(t.Year, t.Month, 1);
        }

        /// <summary>
        /// return the last date in a given month
        /// </summary>
        public static DateTime LastDateOfMonth(DateTime t)
        {
            return new DateTime(t.Year, t.Month, DateTime.DaysInMonth(t.Year, t.Month));
        }
        #endregion

        #region Year
        /// <summary>
        /// return the first date in a given Year
        /// </summary>
        public static DateTime FirstDateOfYear(DateTime t)
        {
            return new DateTime(t.Year, 1, 1);
        }

        /// <summary>
        /// return the last date in a given Year
        /// </summary>
        public static DateTime LastDateOfYear(DateTime t)
        {
            return new DateTime(t.Year, 12, DateTime.DaysInMonth(t.Year, t.Month));
        }
        #endregion

        #endregion

        #region Get Order
        /// <summary>
        /// Gets order of a specific date element define by <see cref="DateElement"/> enum
        /// in a date time format string depends on current <see cref="CultureInfo"/>.
        /// </summary>
        internal static int GetOrder(DateElement element)
        {
            int result = -1;

            string format = UI.Culture.DateTimeFormat.ShortDatePattern;
            string[] splits = format.Split(new string[] { UI.Culture.DateTimeFormat.DateSeparator }, StringSplitOptions.RemoveEmptyEntries);
            if (splits.Length == 3)
            {
                for (int i = 0; i < splits.Length; i++)
                {
                    switch (element)
                    {
                        case DateElement.Day:
                            result = splits[i].ToLower().Contains("d") ? i : result;
                            break;
                        case DateElement.Month:
                            result = splits[i].ToLower().Contains("m") ? i : result;
                            break;
                        case DateElement.Year:
                            result = splits[i].ToLower().Contains("y") ? i : result;
                            break;
                        #region Defensive tracing
                        default:
                            throw new NotSupportedException(string.Format("Do not support this element {0}.", element));
                            break;
                        #endregion
                    }
                    if (result >= 0)
                    {
                        break;
                    }
                    #region Defensive tracing
                    else
                    {
                        // miss match, move next.
                    }
                    #endregion
                }
            }
            #region Defensive tracing
            else
            {
                // Incorrect format, donothing.
            }
            #endregion

            return result;
        }
        #endregion

        #region calculate year
        /// <summary>
        /// Convert from input year with two characters to real number of year.
        /// </summary>
        internal static int CalculateYear(int currentYear, int inputYear)
        {
            string curY, iY = "";
            string temp = "";
            curY = currentYear.ToString();
            iY = inputYear.ToString();

            if (curY.Length <= iY.Length)
                return inputYear;
            else
            {
                temp = curY.Remove(curY.Length - iY.Length);
                return int.Parse(temp + iY);
            }
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor.
        /// </summary>
        private DateTimeHelper()
        { }
        #endregion
    }

    #region Date Element
    /// <summary>
    /// Enum define some elements of a date time.
    /// </summary>
    internal enum DateElement
    {
        /// <summary>
        /// Date element.
        /// </summary>
        Day = 0,
        /// <summary>
        /// Month element.
        /// </summary>
        Month = 1,
        /// <summary>
        /// Year element.
        /// </summary>
        Year = 2
    }
    #endregion
}